import serializer
from rest_framework import serializers
from django.contrib.auth.models import User
from django_redis import get_redis_connection
from rest_framework.exceptions import ValidationError

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from django.contrib.auth import authenticate
from config.dbs.redisConfig import KEY_TEMPLATE
from .models import UserDetail


class UserSerializer(serializers.ModelSerializer):
    #   需要新增 验证码  和 uuid 的校验   进行反序列化
    #  前端能传入  read_only=True 前端能写
    verify = serializers.CharField(write_only=True)
    uuid = serializers.CharField(write_only=True)
    avatar = serializers.CharField(source="userdetail.avatar",read_only=True)
    phone = serializers.CharField(source="userdetail.phone",read_only=True)
    sex = serializers.IntegerField(source="userdetail.sex",read_only=True)
    birthday = serializers.CharField(source="userdetail.birthday",read_only=True)
    class Meta:
        model = User
        # fields = '__all__'
        exclude = ["first_name","groups",
                   "is_staff","last_login","last_name",
                   "user_permissions","username"
        ]
        extra_kwargs = {
            "password":{"write_only":True},
            "is_superuser":{"read_only":True}
        }

    #  自定义 校验规则
    #  对象级别的校验
    #  拿到前端 的 uuid 与 verify
    #  然后拿到redis的 uuid  验证码进行 比对
    def validate(self,attrs):
        #  attrs = {"username":"username","verify":"","uuid":""}
        verify = attrs.get('verify')
        uuid = attrs.get('uuid')

        #  把redis连接信息 作为参数   传入进来 ==》 redis 缓存对象
        cache = get_redis_connection(alias='verify_codes')
    #  get() 查询
        redis_verify = cache.get(KEY_TEMPLATE % ("register",uuid))

        #  删除  客户端输入一次验证码后 后端就直接删除验证码
        cache.delete(KEY_TEMPLATE % ("register",uuid))

#  判断验证码是否一致
        if not redis_verify:
            raise serializers.ValidationError("验证码已过期")

        if verify.upper() != redis_verify.upper():
            raise serializers.ValidationError("验证码错误")
#  验证通过
        return attrs


#  原生的字段的校验的时候使用
# class MyTokenTokenObtainPairSerializer(serializers.Serializer)

#   已经有模型的时候才使用
# class MyTokenTokenObtainPairSerializer(serializers.ModelSerializer)
class MyTokenTokenObtainPairSerializer(TokenObtainPairSerializer):
    # serializers.Serializer《== 密码的校验  《==TokenObtainSerializer       TokenObtainPairSerializer==》  返回token的值
#   反序列化的时候  能让客户端传入 uuid 和 verify 验证码
    verify = serializers.CharField(write_only=True)
    uuid = serializers.CharField(write_only=True)

    #  校验规则
    #  对象级别的校验
    def validate(self, attrs):
        #  attrs 前端传入的数据(username:"bd",password:"password")
        uuid = attrs.get('uuid')
        verify = attrs.get('verify')
        username = attrs.get('username')
        password = attrs.get('password')

        #  与数据库进行校验
        #  uuid verify 的校验==》  redis 数据校验
        #  把redis连接信息 作为参数   传入进来 ==》 redis 缓存对象
        cache = get_redis_connection(alias='verify_codes')
        #  get() 查询
        redis_verify = cache.get(KEY_TEMPLATE % ("login", uuid))

        #  删除  客户端输入一次验证码后 后端就直接删除验证码
        cache.delete(KEY_TEMPLATE % ("login", uuid))

        #  判断验证码是否一致
        if not redis_verify:
            raise serializers.ValidationError("验证码已过期")

        if verify.upper() != redis_verify.upper():
            raise serializers.ValidationError("验证码错误")

        #  用户名和密码的校验
        user = authenticate(username=username,password=password)
        if not user:
            raise serializers.ValidationError("账号或密码错误")


        #  保持会话的状态  制作token令牌
        refresh = self.get_token(user)
        #  返回token的值  返回到客户端进行保存
        return {'user':user.username,'token':str(refresh.access_token)}


#  用户详情的序列化
class UserDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserDetail
        exclude = ['is_delete']


class UpdatePasswordSerializer(serializers.Serializer):
    password = serializers.CharField(max_length=20,min_length=6)
    new_password = serializers.CharField(max_length=20,min_length=6)
    re_new_password = serializers.CharField(max_length=20,min_length=6)

    def validate(self,attrs):
        if attrs.get("new_password") != attrs.get("re_new_password"):
            raise ValidationError('两次密码不一致')
        if attrs.get("password") == attrs.get("new_password"):
            raise ValidationError('原密码和信密码一至')

        #  原密码和数据库比较
        user = self.context['request'].user

        if not user.check_password(attrs.get('password')):
            raise ValidationError('密码输入错误')

        return attrs






